﻿using System;
using System.Collections.Generic;
using System.Text;

namespace DlrBasic.Runtime
{
    public delegate bool NextStateDelegate();

    /// <summary>
    /// Contains BASIC for stack information. Some BASICs may potentially
    /// have several NEXTs for one FOR, and one NEXT for several NEXTs.
    /// </summary>
    public sealed class DlrBasicForStack
    {
        Stack<ForState> stack = new Stack<ForState>();

        public DlrBasicForStack()
        {
        }

        public string CurrentForId
        {
            get { return stack.Peek().ForId; }
        }

        public int GetContinueState()
        {
            return stack.Peek().ContinueState;
        }

        public bool NextAny()
        {
            if (stack.Count == 0) throw new DlrBasicException(Properties.Resources.NextWoForException);

            bool @continue = stack.Peek().ContinueAction();
            if (@continue)
                return true;
            else
            {
                stack.Pop();
                return false;
            }
        }

        void SkipTo(string forId)
        {
            while (stack.Count > 0 && stack.Peek().ForId != forId)
                stack.Pop();
        }

        public bool Next(string forId)
        {
            SkipTo(forId);

            return NextAny();
        }

        public void AddFor(string forId, int continueState, NextStateDelegate continueAction)
        {
            ForState state = new ForState();
            state.ForId = forId;
            state.ContinueState = continueState;
            state.ContinueAction = continueAction;

            stack.Push(state);
        }

        private struct ForState
        {
            public string ForId;
            public int ContinueState;
            public NextStateDelegate ContinueAction;
        }
    }
}
